import os
import uuid
from contextlib import asynccontextmanager
from typing import Dict, Optional

from fastapi import FastAPI, File, UploadFile, HTTPException, BackgroundTasks
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import List
import logging

from asr_service import get_asr_service

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
    handlers=[
        logging.FileHandler('asr_service.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# 数据模型
class SentenceInfo(BaseModel):
    """句子信息模型"""
    text: str = Field(description="转录文本")
    start_time: float = Field(description="开始时间（秒）")
    end_time: float = Field(description="结束时间（秒）")
    speaker_id: Optional[str] = Field(default=None, description="说话人ID")


class TranscriptionResult(BaseModel):
    """转录结果模型"""
    sentence_info: List[SentenceInfo] = Field(description="句子信息列表")
    processing_time: float = Field(description="处理时间（秒）")
    audio_duration: Optional[float] = Field(default=None, description="音频时长（秒）")
    total_text: Optional[str] = Field(default=None, description="完整转录文本")


class HealthResponse(BaseModel):
    """健康检查响应模型"""
    status: str
    message: str


@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理"""
    # 启动阶段
    logger.info("正在启动ASR服务...")
    asr_service = get_asr_service()
    if not asr_service.initialize():
        logger.error("ASR服务初始化失败")
        raise RuntimeError("ASR服务初始化失败")
    logger.info("ASR服务启动成功")
    
    # 运行阶段
    yield
    
    # 关闭阶段
    logger.info("正在关闭ASR服务...")
    asr_service.cleanup()
    logger.info("ASR服务已关闭")


async def cleanup_temp_file(file_path: str):
    """清理临时文件"""
    try:
        if os.path.exists(file_path):
            os.remove(file_path)
            logger.info(f"已清理临时文件: {file_path}")
    except Exception as e:
        logger.error(f"清理临时文件失败: {e}")


# 创建FastAPI应用
app = FastAPI(
    title="ASR Sample",
    description="基于FunASR+Paraformer的简化版语音识别服务",
    version="1.0.0",
    lifespan=lifespan
)

# 配置CORS中间件，允许前端跨域请求
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173", "http://127.0.0.1:5173"],
    allow_credentials=True,
    allow_methods=["GET", "POST"],
    allow_headers=["*"],
)


@app.get("/", response_model=Dict[str, str])
async def root():
    """根路径"""
    return {
        "message": "ASR Sample - 简化版语音识别服务",
        "version": "1.0.0",
        "docs": "/docs"
    }


@app.get("/health", response_model=HealthResponse)
async def health_check():
    """健康检查"""
    asr_service = get_asr_service()
    
    if asr_service.model is not None:
        return HealthResponse(
            status="healthy",
            message="ASR服务运行正常"
        )
    else:
        return HealthResponse(
            status="unhealthy",
            message="ASR模型未加载"
        )


@app.post("/transcribe", response_model=TranscriptionResult)
async def transcribe_audio(
    background_tasks: BackgroundTasks,
    file: UploadFile = File(...)
):
    """音频转录接口"""
    
    # 检查文件格式
    allowed_extensions = ['.wav', '.mp3', '.m4a', '.flac']
    file_ext = os.path.splitext(file.filename)[1].lower()
    
    if file_ext not in allowed_extensions:
        raise HTTPException(
            status_code=400,
            detail=f"不支持的文件格式: {file_ext}。支持的格式: {', '.join(allowed_extensions)}"
        )
    
    # 检查文件大小 (限制200MB)
    max_size = 200 * 1024 * 1024  # 200MB
    file_content = await file.read()
    
    if len(file_content) > max_size:
        raise HTTPException(
            status_code=400,
            detail="文件大小超过限制 (200MB)"
        )
    
    # 保存临时文件
    temp_filename = f"{uuid.uuid4()}{file_ext}"
    temp_path = os.path.join("temp", temp_filename)
    
    try:
        # 确保temp目录存在
        os.makedirs("temp", exist_ok=True)
        
        # 写入文件
        with open(temp_path, "wb") as temp_file:
            temp_file.write(file_content)
        
        # 执行转录
        import time
        start_time = time.time()
        
        asr_service = get_asr_service()
        result = await asr_service.transcribe(temp_path)
        
        processing_time = time.time() - start_time
        
        # 添加后台任务清理临时文件
        background_tasks.add_task(cleanup_temp_file, temp_path)
        
        # 检查转录是否成功
        if not result.get('success', False):
            raise HTTPException(
                status_code=500,
                detail=f"转录失败: {result.get('error', '未知错误')}"
            )
        
        # 构建返回结果
        transcribed_text = result.get('text', '')
        
        # 创建句子信息（简化版，将整个文本作为一个句子）
        sentence_info = []
        if transcribed_text:
            sentence_info.append(SentenceInfo(
                text=transcribed_text,
                start_time=0.0,
                end_time=0.0,  # 简化版不提供时间戳
                speaker_id=None
            ))
        
        # 返回结果
        return TranscriptionResult(
            sentence_info=sentence_info,
            processing_time=processing_time,
            audio_duration=None,  # 简化版不计算音频时长
            total_text=transcribed_text
        )
        
    except Exception as e:
        # 出错时立即清理临时文件
        cleanup_temp_file(temp_path)
        
        raise HTTPException(
            status_code=500,
            detail=f"转录失败: {str(e)}"
        )


@app.exception_handler(Exception)
async def global_exception_handler(request, exc):
    """全局异常处理器"""
    logger.error(f"未处理的异常: {str(exc)}")
    return JSONResponse(
        status_code=500,
        content={"detail": "服务器内部错误"}
    )


if __name__ == "__main__":
    import uvicorn
    
    logger.info("启动 ASR Sample 服务...")
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=8001,
        reload=False,
        log_level="info"
    )